<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Model;

use App\Exception\InternalException;
use Hyperf\Cache\Driver\RedisDriver;
use Hyperf\DbConnection\Model\Model as BaseModel;
use Hyperf\Di\Annotation\Inject;
use Hyperf\ModelCache\Cacheable;
use Hyperf\ModelCache\CacheableInterface;
use App\Traits\Model\Model as ModelTraits;
use Hyperf\Redis\Redis;
use Psr\Container\ContainerInterface;
use Psr\SimpleCache\CacheInterface;
use function Hyperf\Config\config;

abstract class Model extends BaseModel implements CacheableInterface
{
    use Cacheable, ModelTraits;

    #[Inject]
    protected ContainerInterface $container;

    /**
     * 生成编码
     * @return int
     */
    protected function getCode(int $len=3, string $type='number', string $field='code')
    {
        switch ($type) {
            case 'number':
                $start = (int)str_pad('1', $len, '0', STR_PAD_RIGHT);
                $end = (int)str_pad('9', $len, '9', STR_PAD_RIGHT);
                $code = mt_rand($start, $end);
                break;
            case 'string':
                $chars = [
                    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n',
                    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
                    '1', '2', '3', '4', '5', '6', '7', '8', '9'
                ];
                $randoms = array_rand($chars, $len);
                shuffle($randoms);
                $code = '';
                foreach ($randoms as $random) {
                    $code .= $chars[$random];
                }
                break;
            default:
                throw new InternalException();
        }

        if ($this->where($field, $code)->exists()) {
            return $this->getCode();
        }

        return $code;
    }

    /**
     * 获取单号
     * @param string $field
     * @param string $prefix
     * @param string $extend
     * @return string
     */
    public function getNo(string $field='no', string $prefix='', string $extend='')
    {
        $keyName = config('cache.default.prefix').$this->getTable()."_{$field}";

        /** @var RedisDriver $cache */
        $cache = $this->container->get(CacheInterface::class);
        /** @var Redis $connection */
        $connection = $cache->getConnection();
        $noSerial = $connection->incr($keyName);
        $noSerial += 100000;

        [$micro] = getMicrosecond();
        $micro = substr($micro, -2);
        return $prefix.date('YmdHis').$noSerial.$micro.$extend;

//        if ($this->withoutGlobalScopes()->where($field, $no)->exists()) {
//            return $this->getNo();
//        }
//        return $no;
    }

    /**
     * 隐藏字段
     * @var array|string[]
     */
    protected array $hidden = [
        'updated_at',
        'deleted_at'
    ];
}
